package sim;

import java.awt.Color;
import java.io.BufferedReader;
import java.io.FileReader;
import java.util.Scanner;
import java.util.StringTokenizer;

import comm.TaskNode;
import env.*;
import static sim.Constants.*;
import static sim.Sim.*;

/**
 * The config file reader.
 */
public class ConfigReader {
	private static int[] pos, size, f;
	private static Scanner scan;
	private static StringTokenizer st;
	private static String token;

	public static void read(String filename) throws Exception {
		BufferedReader br = new BufferedReader(new FileReader(filename));
		while ((token = br.readLine()) != null) {
			if (token.startsWith("general"))
				readGeneral(token);
			else if (token.startsWith("goal"))
				readGoal(token);
			else if (token.startsWith("bot"))
				readRobot(token);
			else if (token.startsWith("obj"))
				readObjValues(token);
			else if (token.startsWith("obs"))
				readObsValues(token);
			else if (token.startsWith("task"))
				readTask(token);
		}
		br.close();
	}

	private static Color readColor(String s) {
		scan = new Scanner(s);
		scan.useDelimiter(",");
		return new Color(scan.nextInt(), scan.nextInt(), scan.nextInt());
	}

	private static void readGeneral(String s) {
		st = new StringTokenizer(s);

		size = new int[] { DEFAULT_WIDTH, DEFAULT_HEIGHT };
		int res = DEFAULT_RES, r = DEFAULT_RUNS, d = DEFAULT_DELAY, t = DEFAULT_STEP_LIMIT;
		Color c = DEFAULT_TEXT_COLOR;

		while (st.hasMoreTokens()) {
			token = st.nextToken();
			if (token.startsWith("size="))
				size = readPair(token.substring(5));
			else if (token.startsWith("res="))
				res = new Integer(token.substring(4));
			else if (token.startsWith("runs="))
				r = new Integer(token.substring(5));
			else if (token.startsWith("delay="))
				d = new Integer(token.substring(6));
			else if (token.startsWith("stepLimit="))
				t = new Integer(token.substring(10));
			else if (token.startsWith("textColor="))
				c = readColor(token.substring(10));
			else if (token.startsWith("NO_TRACE"))
				drawTrace = false;
		}

		screenWidth = size[0];
		screenHeight = size[1];
		Potential.init(res, screenWidth, screenHeight);
		runs = r;
		delay = d;
		stepLimit = t;
		textColor = c;
	}

	private static void readGoal(String s) {
		st = new StringTokenizer(s);

		pos = new int[] { screenWidth / 2, screenHeight };
		int r = DEFAULT_GOAL_RADIUS;
		Color color = DEFAULT_GOAL_COLOR;
		Goal g;

		while (st.hasMoreTokens()) {
			token = st.nextToken();
			if (token.startsWith("pos="))
				pos = readPair(token.substring(4));
			else if (token.startsWith("r="))
				r = new Integer(token.substring(2));
			else if (token.startsWith("color="))
				color = readColor(token.substring(6));
		}

		g = new Goal(pos[0], pos[1], r);
		g.color = color;
		goal = g;
	}

	private static void readRobot(String s) {
		st = new StringTokenizer(s);

		pos = new int[] { 0, 0 };
		size = new int[] { DEFAULT_ROBOT_WIDTH, DEFAULT_ROBOT_HEIGHT };
		String id = null;
		int angle = 0, vmax = DEFAULT_ROBOT_VMAX, pmax = DEFAULT_ROBOT_PMAX, fmax = DEFAULT_ROBOT_FMAX, drawType = DEFAULT_ROBOT_DRAWTYPE;
		Color color = DEFAULT_ROBOT_COLOR;
		int cost = DEFAULT_ROBOT_COST;
		int c = DEFAULT_CAP;

		while (st.hasMoreTokens()) {
			token = st.nextToken();
			if (token.startsWith("id="))
				id = new String(token.substring(3));
			else if (token.startsWith("pos="))
				pos = readPair(token.substring(4));
			else if (token.startsWith("size="))
				size = readPair(token.substring(5));
			else if (token.startsWith("a="))
				angle = new Integer(token.substring(2));
			else if (token.startsWith("v="))
				vmax = new Integer(token.substring(2));
			else if (token.startsWith("p="))
				pmax = new Integer(token.substring(2));
			else if (token.startsWith("f="))
				fmax = new Integer(token.substring(2));
			else if (token.startsWith("c="))
				c = readCap(token.substring(2));
			else if (token.startsWith("shape="))
				drawType = new Integer(token.substring(6));
			else if (token.startsWith("color="))
				color = readColor(token.substring(6));
			else if (token.startsWith("cost="))
				cost = new Integer(token.substring(5));
		}

		size = swap_to_desc(size);
		addRobot(id, pos[0], pos[1], size[0], size[1], angle, vmax, pmax, fmax,cost, c, color, drawType);
	}

	private static void readObjValues(String s) {
		st = new StringTokenizer(s);

		pos = new int[] { 0, 0 };
		size = new int[] { DEFAULT_OBJ_WIDTH, DEFAULT_OBJ_HEIGHT };
		f = new int[] { DEFAULT_OBJ_F1, DEFAULT_OBJ_F2 };
		String id = null;
		int angle = 0, c = DEFAULT_CAP;
		Color color = DEFAULT_OBJ_COLOR;

		while (st.hasMoreTokens()) {
			token = st.nextToken();
			if (token.startsWith("id="))
				id = new String(token.substring(3));
			else if (token.startsWith("pos="))
				pos = readPair(token.substring(4));
			else if (token.startsWith("size="))
				size = readPair(token.substring(5));
			else if (token.startsWith("a="))
				angle = new Integer(token.substring(2));
			else if (token.startsWith("f="))
				f = readPair(token.substring(2));
			else if (token.startsWith("c="))
				c = readCap(token.substring(2));
			else if (token.startsWith("color="))
				color = readColor(token.substring(6));
		}

		size = swap_to_desc(size);
		addObj(id, pos[0], pos[1], size[0], size[1], angle, c, f[0], f[1], color);
	}

	private static void readObsValues(String s) {
		st = new StringTokenizer(s);

		int r = DEFAULT_OBS_RADIUS;

		while (st.hasMoreTokens()) {
			token = st.nextToken();
			if (token.startsWith("pos="))
				pos = readPair(token.substring(4));
			else if (token.startsWith("r="))
				r = new Integer(token.substring(2));
		}

		addObstacle(pos[0], pos[1], r);
	}

	private static void readTask(String s) throws Exception {
		st = new StringTokenizer(s);

		TaskNode t = null;

		while (st.hasMoreTokens()) {
			token = st.nextToken();
			if (token.startsWith("id="))
				t = getTask(token.substring(3));
			else if (token.startsWith("priority="))
				t.priority = new Double(token.substring(9));
			else if (token.startsWith("bias="))
				t.bias = new Double(token.substring(5));
			else if (token.startsWith("next="))
				readSucc(token.substring(5), t);
		}
	}

	private static int[] readPair(String s) {
		scan = new Scanner(s);
		scan.useDelimiter(",");
		return new int[] { scan.nextInt(), scan.nextInt() };
	}

	private static int[] swap_to_desc(int[] pair) {
		if (pair[1] > pair[0])
			return new int[] { pair[1], pair[0] };
		else
			return pair;
	}

	private static int readCap(String s) {
		scan = new Scanner(s);
		scan.useDelimiter(",");
		int c = 0;
		while (scan.hasNextInt())
			c += 1 << scan.nextInt();
		return c;
	}

	private static void readSucc(String s, TaskNode t) {
		scan = new Scanner(s);
		scan.useDelimiter(",");
		while (scan.hasNext())
			t.addSucc(getTask(scan.next()));
	}
}
